<template>
  <div class="table-search" :class="{'noMar': toolSettings.length === 0}">
    <!-- 搜索区 -->
    <div class="ts__coms">
      <a-row>
        <a-col v-for="(item, index) in fields" :key="index" :md="md" :lg="lg" v-show="!item.hidden">
          <div v-if="item.type === 'slot'" class="search__item">
            <slot :name="item.slotName" :target="item" />
          </div>
          <div v-if="item.type === 'input'" class="search__item">
            <label>{{ item.label }}</label>
            <a-input :allow-clear="!item.allowClear" class="f1" v-model="item.value" :placeholder="item.placeholder"></a-input>
          </div>
          <div v-if="item.type === 'select'" class="search__item">
            <label>{{ item.label }}</label>
            <a-select
              class="f1"
              v-model="item.value"
              :disabled="item.disabled"
              :placeholder="!item.disabled ? item.placeholder : item.disabledPlaceholder"
              :allowClear="!item.disabled"
              :show-search="item.search"
              :filterOption="item.selectFilter || selectFilter"
              @change="item.change ? item.change(item, fields) : selectChange(item, fields)">
              <a-select-option
                v-for="option in item.options"
                :key="option[item.valueKey] || option.value"
                :value="option[item.valueKey] || option.value">
                {{ option[item.labelKey] || option.label }}
              </a-select-option>
            </a-select>
          </div>
          <div v-if="item.type === 'date'" class="search__item">
            <label>{{ item.label }}</label>
            <a-date-picker
              :valueFormat="item.valueFormat || 'YYYY-MM-DD'"
              class="f1"
              v-model="item.value"
              :placeholder="item.placeholder"
              :disabled="item.disabled"
            />
          </div>
          <div v-if="item.type === 'month'" class="search__item">
            <label>{{ item.label }}</label>
            <a-month-picker
              class="f1"
              v-model="item.value"
              :placeholder="item.placeholder"
              :disabled="item.disabled"
            />
          </div>
          <div v-if="item.type === 'range'" class="search__item">
            <label>{{ item.label }}</label>
            <a-range-picker
              :valueFormat="item.valueFormat || 'YYYY-MM-DD'"
              :format="item.format || 'YYYY-MM-DD'"
              class="f1"
              v-model="item.value"
              :showTime="item.showTime ? item.showTime : null"
              :disabled="item.disabled"
            />
          </div>
          <div v-if="item.type === 'tree-select'" class="search__item">
            <label>{{ item.label }}</label>
            <a-tree-select
              class="f1"
              :placeholder="item.placeholder"
              :tree-data="item.options"
              :replaceFields="{ children: item.childrenKey || 'children', title: item.labelKey, key: item.valueKey, value: item.valueKey }"
              v-model="item.value"
              :disabled="item.disabled"
            />
          </div>
          <div v-if="item.type === 'checkbox'" class="search__item">
            <label>{{ item.label }}</label>
            <a-checkbox-group
              :options="item.options"
              :disabled="item.disabled"
              v-model="item.value"
            />
          </div>
        </a-col>
        <a-col :md="(4-showFieldCount%4)*6" :sm="24">
          <div class="ts__btns search__item" style="padding: 0">
            <a-button @click.stop="search" v-if="!isHideSearchBtn" :type="searchBtnOpt.type" :icon="searchBtnOpt.icon" class="ts__btns-b">{{ searchBtnOpt.text }}</a-button>
            <a-button @click.stop="reset" v-if="!isHideResetBtn" :type="resetBtnOpt.type" :icon="resetBtnOpt.icon">{{ resetBtnOpt.text }}</a-button>
            <a-button v-if="fields.length >= stretchThreshold" @click.stop="stretch" type="link" :icon="toggle ? 'up' : 'down'">
              {{ toggle ? '收起' : '展开' }}
            </a-button>
          </div>
        </a-col>
      </a-row>
    </div>
    <!-- 功能区 -->
    <div class="ts__tools">
      <div class="ts__tools-l">
        <template v-for="(tool, idx) in toolSettings">
          <!--  分有权限控制按钮和无权限控制按钮 -->
          <a-button
            v-if="tool.power"
            v-hasPermi="tool.power"
            :key="idx"
            class="ts__btns-b"
            :type="tool.type"
            :style="toColor(tool.type)"
            :icon="tool.icon"
            :loading="tool.loading"
            @click="tool.click ? tool.click() : null">
            {{ tool.text }}
          </a-button>
          <a-button
            v-else
            class="ts__btns-b"
            :key="tool.text"
            :loading="tool.loading"
            :type="tool.type"
            :style="toColor(tool.type)"
            :icon="tool.icon"
            @click="tool.click ? tool.click() : null">
            {{ tool.text }}
          </a-button>
        </template>
        <slot name="toolLeft" />
      </div>
      <div class="ts__tools-r">
        <a-popconfirm
          overlayClassName="ts-popconfirm"
          placement="leftTop"
          ok-text="确定"
          cancel-text="取消"
          :icon="(h) => h('span')"
          @confirm="fieldConfirm"
          @visibleChange="fieldVisibleChange"
        >
          <template slot="title">
            <div class="field">
              <a-checkbox
                class="field__checkbox"
                :checked="showFields.checkAll"
                @change="showFieldsAllChange">
                全选
              </a-checkbox>
              <a-tree
                v-model="showFields.checkedKeys"
                :tree-data="showFields.treeData"
                checkable
                :replaceFields="{ key: 'dataIndex' }"
                @check="showFieldsCheck"
              />
            </div>
          </template>
          <a-button
            v-if="uuid"
            type="dashed"
            shape="circle"
            icon="line-height"
            title="显示字段"
            class="refresh" />
        </a-popconfirm>
        <a-button
          v-if="isRefreshBtn"
          :loading="loading"
          @click.stop="refresh"
          type="dashed"
          shape="circle"
          icon="reload"
          title="刷新"
          class="refresh" />
      </div>
    </div>
  </div>
</template>

<script>
const SHOW_FIELD = 'field_table_columns'
export default {
  name: 'TableSearch',
  props: {
    fields: {
      type: Array,
      default: () => []
    },
    searchBtn: {
      type: [String, Object],
      default: '搜索'
    },
    isHideSearchBtn: Boolean,
    resetBtn: {
      type: [String, Object],
      default: '重置'
    },
    isHideResetBtn: Boolean,
    // 伸缩阈值, 默认超过八个(包含八)搜索条件时, 就会出现伸缩控制按钮
    stretchThreshold: {
      type: Number,
      default: 8
    },
    // 展示的个数, 默认展示7个
    stretchExsitNum: {
      type: Number,
      default: 7
    },
    isRefreshBtn: Boolean,
    loading: Boolean,
    // 功能按钮区
    toolSettings: {
      type: Array,
      default: () => []
    },
    // label的统一宽度, 为了满足一些强迫症, 能控制input长度一致
    labelWidth: {
      type: [Number, String],
      default: 'auto'
    },
    md: {
      type: Number,
      default: 12
    },
    lg: {
      type: Number,
      default: 6
    },
    columns: {
      type: Array,
      default: () => []
    },
    uuid: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      toggle: false,
      showFieldCount: 0,
      initFields: null,
      selectFilter (inputValue, option) {
        return (option.componentOptions.children[0].text.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0)
      },
      // 展示字段
      showFields: {
        treeData: [],
        checkedKeys: [],
        checkAll: false,
        total: 0
      }
    }
  },
  computed: {
    searchBtnOpt () {
      const btnInit = { text: '搜索', icon: 'search', type: 'primary' }
      if (typeof this.searchBtn === 'string') btnInit.text = this.searchBtn
      return { ...btnInit, ...this.searchBtn }
    },
    resetBtnOpt () {
      const btnInit = { text: '重置', icon: 'reload', type: '' }
      if (typeof this.searchBtn === 'string') btnInit.text = this.resetBtn
      return { ...btnInit, ...this.resetBtn }
    },
    toColor () {
      return color => {
        if (!color) return {}
        const isColor = color.indexOf('#') !== -1
        if (!isColor) return {}
        return {
          color: '#fff',
          backgroundColor: color,
          borderColor: color
        }
      }
    }
  },
  created () {
    this.initFields = JSON.parse(JSON.stringify(this.fields))
    this.stretchHandle()

    this.uuid && this.initShowField()
  },
  mounted () {
    const labelDoms = document.querySelectorAll('.ts__coms label')
    labelDoms.forEach(dom => { dom.style.width = typeof this.labelWidth === 'string' ? this.labelWidth : this.labelWidth + 'px' })
  },
  methods: {
    // 显示字段
    initShowField () {
      let fieldTableColumns = JSON.parse(localStorage.getItem(SHOW_FIELD))
      // 初始化缓存
      if (!fieldTableColumns) {
        fieldTableColumns = {}
        localStorage.setItem(SHOW_FIELD, JSON.stringify(fieldTableColumns))
      }
      // 初始化树形数据
      this.showFields.treeData = JSON.parse(JSON.stringify(this.columns))
      // 初始化选中的数据
      this.showFields.checkedKeys = fieldTableColumns[this.uuid] || []

      let total = 0
      const keys = []
      const handleTree = (tree) => {
        tree.forEach(item => {
          total++
          keys.push(item.dataIndex)
          if (item.children && item.children.length !== 0) {
            handleTree(item.children)
          }
        })
      }
      handleTree(this.showFields.treeData)
      this.showFields.total = total
      if (this.showFields.checkedKeys.length === 0) this.showFields.checkedKeys = keys
      if (total === this.showFields.checkedKeys.length) this.showFields.checkAll = true

      // 同步表格变化
      this.syncTableFieldChange()
    },
    showFieldsCheck () {
      this.showFields.checkAll = this.showFields.total === this.showFields.checkedKeys.length
    },
    showFieldsAllChange () {
      this.showFields.checkAll = !this.showFields.checkAll
      this.allChecked()
    },
    allChecked () {
      if (!this.showFields.checkAll) {
        this.showFields.checkedKeys = []
      } else {
        const handleTree = (tree, result) => {
          tree.forEach(item => {
            if (item.children && item.children.length !== 0) {
              handleTree(item.children, result)
            } else {
              result.push(item.dataIndex)
            }
          })
        }
        const result = []
        handleTree(this.showFields.treeData, result)
        this.showFields.checkedKeys = result
      }
    },
    fieldConfirm () {
      const fieldTableColumns = JSON.parse(localStorage.getItem(SHOW_FIELD))
      fieldTableColumns[this.uuid] = this.showFields.checkedKeys
      localStorage.setItem(SHOW_FIELD, JSON.stringify(fieldTableColumns))
      this.syncTableFieldChange()
    },
    fieldVisibleChange (visible) {
      if (!visible) this.fieldConfirm()
    },
    syncTableFieldChange () {
      const keys = this.showFields.checkedKeys
      const tree = JSON.parse(JSON.stringify(this.showFields.treeData))
      const handleTree = (tree) => {
        return tree.filter(item => {
          if (item.children && item.children.length !== 0) {
            const children = handleTree(item.children)
            item.children = children
            if (children.length > 0) return item
          } else {
            return keys.includes(item.dataIndex)
          }
        })
      }
      const newColumns = handleTree(tree)
      this.$emit('update:columns', newColumns)
    },
    // 某个下拉框的值改变
    selectChange (item, fields) {
      this.$emit('selectChangeEmit', item, fields)
    },
    // 搜索
    search () {
      this.$emit('searchEmit', this.fields)
    },
    // 重置
    reset () {
      if (this.fields.length) {
        this.fields.forEach(item => {
          switch (item.type) {
            case 'range': item.value = []; break
            case 'select': item.value = undefined; break
            case 'tree-select': item.value = undefined; break
            default: item.value = ''
          }
        })
      }
      this.$emit('resetEmit', this.fields)
    },
    // 收起/展开
    stretch () {
      this.toggle = !this.toggle
      this.stretchHandle()
    },
    // 处理伸缩逻辑
    stretchHandle () {
      this.showFieldCount = 0
      this.fields.forEach((item, index) => {
        if ((index + 1) > this.stretchExsitNum) item.hidden = !this.toggle
        if (!item.hidden) this.showFieldCount++
      })
    },
    // 刷新
    refresh () {
      this.$emit('refreshEmit', this.fields)
    },
    // 辅助函数
    auxiliary (field, fields) {
      if (fields) return fields.find(a => a.field === field)
      return this.fields.find(a => a.field === field)
    },
    assignParams (params) {
      for (const key in params) {
        const target = this.auxiliary(key)
        if (target) params[key] = target.value
      }
      // 处理一些特殊类型
      this.specialTypeHandle(params)
    },
    resetParams (params) {
      for (const key in params) {
        const target = this.auxiliary(key, this.initFields)
        if (target) params[key] = target.value
      }
      // 处理一些特殊类型
      this.specialTypeHandle(params)
    },
    // 处理一些特殊类型
    specialTypeHandle (params) {
      this.fields.forEach(item => {
        if (item.field.startsWith('range-')) {
          const prefix = item.field.split('-')
          if (prefix.length === 3) {
            params[prefix[1]] = item.value[0] || ''
            params[prefix[2]] = item.value[1] || ''
          } else {
            const prefixKey = prefix[1]
            params[prefixKey + 'Start'] = item.value[0] || ''
            params[prefixKey + 'End'] = item.value[1] || ''
          }
        }
      })
    }
  }
}
</script>

<style scoped>
.table-search{
  margin-bottom: 16px;
}
.table-search.noMar{
  margin-bottom: 0;
}
.ts__coms{
  margin-bottom: 12px;
}
.search__item{
  width: 100%;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  height: 42px;
  padding: 0 8px;
}
.search__item label{
  min-width: 68px;
  white-space: nowrap;
  font-size: 14px;
  color: rgba(0, 0, 0, 0.85);
  box-sizing: border-box;
  padding-right: 10px;
}
.ts__btns{
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
.ts__btns-b{
  margin-right: 8px;
}
.ts__btns-r{
  color: #fff;
}
.ts__tools{
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.ts__tools-l{
  display: flex;
  align-items: center;
}
.ts__tools-r{
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.refresh{
  margin-left: 14px;
}
/* 限制字段 */
.field{
  width: 200px;
  height: 240px;
  overflow-x: auto;
  overflow-y: auto;
  margin-bottom: 2px;
  margin-top: 6px;
}
.field__checkbox{
  margin-left: 26px;
  margin-bottom: 2px;
}

.f1{
  flex: 1;
}
::v-deep .refresh.ant-btn .anticon{
  line-height: 1.4 !important;
}
</style>

<style>
.ts-popconfirm .ant-popover-message-title{
  padding-left: 0 !important;
}
.ts-popconfirm .ant-popover-inner-content{
  padding-left: 6px !important;
  padding-right: 12px !important;
  padding-bottom: 10px;
}
</style>
